package cn.lingyangwl.agile.infra.file.manager;

import cn.lingyangwl.agile.infra.module.file.constants.FileCacheCons;
import cn.lingyangwl.agile.infra.file.mapper.FileConfigMapper;
import cn.lingyangwl.agile.infra.module.file.model.entity.FileConfig;
import cn.lingyangwl.agile.model.module.tenant.TenantContext;
import cn.lingyangwl.framework.cache.core.service.CacheService;
import cn.lingyangwl.framework.mybatis.mate.annotations.FieldUniqueCheck;
import cn.lingyangwl.framework.mybatis.mate.enums.OperationTypeEnum;
import cn.lingyangwl.framework.tool.core.CollectionUtils;
import cn.lingyangwl.framework.tool.core.UrlUtils;
import cn.lingyangwl.framework.tool.core.exception.BizException;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 文件配置 仓储层
 *
 * @author shenguangyang
 */
@Slf4j
@Repository
public class FileConfigManager extends ServiceImpl<FileConfigMapper, FileConfig>
    implements IService<FileConfig> {

    @Resource
    private CacheService cacheService;

    @FieldUniqueCheck(type = OperationTypeEnum.SAVE)
    public boolean saveFileConfig(FileConfig entity) {
        entity.setPath(UrlUtils.removeRepeatSlashOfUrl("/" + entity.getPath()));
        return this.save(entity);
    }

    @FieldUniqueCheck(type = OperationTypeEnum.UPDATE)
    public boolean updateFileConfigById(FileConfig entity) {
        cacheService.opsForKey().delete(String.format(FileCacheCons.FILE_CONFIG_KEY, entity.getBizType()));
        return this.updateById(entity);
    }

    public FileConfig getFileConfigByBizType(String bizType) {
        String key = String.format(FileCacheCons.FILE_CONFIG_KEY, bizType);
        Object object = cacheService.opsForValue().get(key);
        if (Objects.isNull(object)) {
            FileConfig fileConfig = this.getOne(FileConfig.lqw().eq(FileConfig::getBizType, bizType));
            if (Objects.isNull(fileConfig)) {
                log.error("未查找到业务类型 [{}] 对应的配置, tenantInfo: {}", bizType, JSON.toJSONString(TenantContext.get()));
                throw new BizException("未查找到业务类型 [{}] 对应的配置", bizType);
            }
            cacheService.opsForValue().set(key, fileConfig);
            return fileConfig;
        } else {
            return (FileConfig) object;
        }
    }

    public boolean deleteFileConfigByIds(List<Long> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return false;
        }
        List<FileConfig> fileConfigList = this.listByIds(ids);
        Set<String> cacheKey = fileConfigList.stream().map(FileConfig::getBizType)
                .map(e -> String.format(FileCacheCons.FILE_CONFIG_KEY, e))
                .collect(Collectors.toSet());
        cacheService.opsForKey().delete(cacheKey);
        return this.removeByIds(ids);
    }

    public List<FileConfig> listFileConfigByBizTypes(List<String> bizTypes) {
        if (CollectionUtils.isEmpty(bizTypes)) {
            return Collections.emptyList();
        }
        return this.list(FileConfig.lqw().in(FileConfig::getBizType, bizTypes));
    }
}
